#pragma once
#include <SimpleDef.h>
#include <Utility/intrinsic.h>
#define INT_GATE_PRESENT (1)
#define INT_GATE_ABSENT (0)
#define INT_GATE_USER (3)
#define INT_GATE_SUPERVISOR (0)

extern LPVOID* g_lpIntStack;
#define INT_STACK_SIZE (4096)

/* 拼接中断门描述符 */
#define MAKE_INT_GATE_DESCRIPTOR(ig_offset, ig_selector, ig_dpl, ig_p) \
( \
    ((QWORD) ig_offset & 0x0000FFFFllu) | /* [15:0] 偏移量低 16 位 */ \
    ((QWORD) ig_selector << 16) | /* [31:16] 选择子 */ \
    (0b0000111000000000llu << 32) | /* [36:32] Reserved; [44:37] 固定标识 */ \
    ((QWORD)ig_dpl << 45) | /* [46:45] DPL */ \
    ((QWORD)ig_p << 47) | /* [47] Present bit */ \
    (((QWORD)ig_offset & 0xFFFF0000llu) << 32) /* [63:48] 偏移量高 16 位 */ \
)

typedef struct __IntExceptContext
{
    DWORD dwEDI;
    DWORD dwESI;
    DWORD dwEBX;
    DWORD dwEBP;
    DWORD dwEDX;
    DWORD dwECX;
    DWORD dwEAX;
    DWORD dwGS;
    DWORD dwFS;
    DWORD dwES;
    DWORD dwDS;
    DWORD dwVector;
    DWORD dwErrorCode;
    DWORD dwEIP;
    DWORD dwCS;
    DWORD dwEFLAGS;
    DWORD dwESP;
    DWORD dwSS;
} IntExceptContext, *LPIntExceptContext; // 中断、异常现场

void DispatchIntExceptHandler(LPIntExceptContext lpIntExceptContext);
static inline LPVOID GetIntStackAddress()
{
    return (LPVOID)((DWORD)g_lpIntStack[GetCurrentCPUCore()] + INT_STACK_SIZE);
}